package com.zhiyou.app.common.util;

import cn.hutool.cache.impl.TimedCache;
import com.zhiyou.app.common.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;

/**
 * @author zhangqiang
 * @date 2023/02/07 15:09
 * @desc sseEmitter发送工具类
 */
@Slf4j
public class SseEmitterSender {
    private final static TimedCache<String, SseEmitter> sseEmitterMap = new TimedCache<>(1000 * 60 * 60);

    public static void send(String orderNum, String data) {
        if (orderNum == null || orderNum.isEmpty()) {
            return;
        }
        SseEmitter sseEmitter = getOrderSse(orderNum, false);
        try {
            if (sseEmitter == null) {
                return;
            }
            sseEmitter.send(data);
        } catch (IOException e) {
            log.warn("send sseEmitter error:{}", e.getMessage());
        }
    }

    public static void sendWithDone(String orderNum, String data) {
        send(orderNum, data);
        complete(orderNum);
        removeSseTask(orderNum);
    }

    public static SseEmitter getNewSseClient(String orderNum) {
        return getOrderSse(orderNum, true);
    }

    public static void complete(String orderNum) {
        if (orderNum == null || orderNum.isEmpty()) {
            return;
        }
        SseEmitter sseEmitter = getOrderSse(orderNum, false);
        if (sseEmitter != null) {
            sseEmitter.complete();
        }
        removeSseTask(orderNum);
    }

    private static SseEmitter getOrderSse(String orderNum, boolean isNew) {
        if (orderNum == null || orderNum.isEmpty()) {
            throw new BizException("orderNum is empty");
        }
        if (isNew) {
            SseEmitter sseEmitter = new SseEmitter(60 * 60 * 1000L);
            sseEmitter.onCompletion(() -> {
                removeSseTask(orderNum);
                log.info("remove completed sseclinet:{},result:{}", orderNum, !sseEmitterMap.containsKey(orderNum));
            });
            sseEmitter.onError((e) -> {
                removeSseTask(orderNum);
                log.warn("sse错误");
            });
            sseEmitterMap.put(orderNum, sseEmitter);
            return sseEmitter;
        } else {
            return sseEmitterMap.get(orderNum, true);
        }
    }

    private static void removeSseTask(String orderNum) {
        sseEmitterMap.remove(orderNum);
    }
}
